package cn.ilovese.collect.serviceimpl.recommend;

import cn.ilovese.collect.datamapper.recommend.RecommendRuleMapper;
import cn.ilovese.collect.datamapper.task.TaskMapper;
import cn.ilovese.collect.datamapper.user.UserMapper;
import cn.ilovese.collect.datamapper.work.WorkMapper;
import cn.ilovese.collect.po.recommend.RecommendRule;
import cn.ilovese.collect.po.task.Task;
import cn.ilovese.collect.po.user.User;
import cn.ilovese.collect.po.work.Work;
import cn.ilovese.collect.service.recommend.RecommendService;
import cn.ilovese.collect.serviceimpl.recommend.strategy.LatestDDLFirstStrategy;
import cn.ilovese.collect.serviceimpl.recommend.strategy.TaskAcceptedStrategy;
import cn.ilovese.collect.serviceimpl.recommend.strategy.WorkerStaticMatchingTaskStrategy;
import cn.ilovese.collect.util.Constant;
import cn.ilovese.collect.util.RecommendUtil;
import cn.ilovese.collect.vo.NullVO;
import cn.ilovese.collect.vo.ResultVO;
import cn.ilovese.collect.vo.recommend.RecommendRuleHaveNameVO;
import cn.ilovese.collect.vo.recommend.RecommendRuleVO;
import cn.ilovese.collect.vo.task.TaskRecommendVO;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;

@Service
public class RecommendServiceImpl implements RecommendService {

    @Resource
    RecommendRuleMapper recommendRuleMapper;

    @Resource
    UserMapper userMapper;

    @Resource
    TaskMapper taskMapper;

    @Resource
    WorkMapper workMapper;

    @Override
    public ResultVO<RecommendRuleVO> createRecommendRule(RecommendRuleVO recommendRuleVO) {
        RecommendRule record = new RecommendRule(recommendRuleVO);
        int id = recommendRuleMapper.insert(record);
        if(id < 1)
            return new ResultVO<>(Constant.REQUEST_FAIL, "插入失败");
        else{
            RecommendRuleVO res = new RecommendRuleVO(record);
            return new ResultVO<>(Constant.REQUEST_SUCCESS,"插入成功",res);
        }
    }

    @Override
    public ResultVO<RecommendRuleVO> updateRecommendRule(RecommendRuleVO recommendRuleVO) {
        int id = recommendRuleVO.getId();
        System.out.println(id);
        if(recommendRuleMapper.selectByPrimaryKey(id) == null)
            return new ResultVO<>(Constant.REQUEST_FAIL, "不存在此推荐规则");
        RecommendRule newRule = new RecommendRule(recommendRuleVO);
        newRule.setId(id);
        int res = recommendRuleMapper.updateByPrimaryKey(newRule);
        if(res == 0)
            return new ResultVO<>(Constant.REQUEST_FAIL, "更新失败");
        return new ResultVO<>(Constant.REQUEST_SUCCESS,"更新成功",new RecommendRuleVO(newRule));
    }

    @Override
    public ResultVO<List<RecommendRuleHaveNameVO>> getAllRecommendRules() {
        List<RecommendRule> temp = recommendRuleMapper.selectAll();
        if(temp.size() == 0)
            return new ResultVO<>(Constant.REQUEST_FAIL,"当前没有制定推荐规则");
        List<RecommendRuleHaveNameVO> res = new ArrayList<>();
        for(RecommendRule recommendRule: temp){
            res.add(new RecommendRuleHaveNameVO(recommendRule));
        }
        return new ResultVO<>(Constant.REQUEST_SUCCESS,"获取推荐规则成功",res);
    }

    @Override
    public ResultVO<NullVO> deleteRecommendRule(Integer ruleid) {
        int id = recommendRuleMapper.deleteByPrimaryKey(ruleid);
        System.out.println("id:" + id);
        if(id < 1)
            return new ResultVO<>(Constant.REQUEST_FAIL,"删除失败");
        return new ResultVO<>(Constant.REQUEST_SUCCESS, "删除成功");
    }

    @Override
    public ResultVO<RecommendRuleVO> getRecommendRuleDetail(Integer ruleid) {
        RecommendRule recommendRule = recommendRuleMapper.selectByPrimaryKey(ruleid);
        if(recommendRule == null)
            return new ResultVO<>(Constant.REQUEST_FAIL,"获取推荐规则详细信息失败");
        return new ResultVO<>(Constant.REQUEST_SUCCESS,"获取推荐规则详细信息成功", new RecommendRuleVO(recommendRule));
    }

    @Override
    public ResultVO<List<TaskRecommendVO>> executeRecommendRule(Integer ruleid,Integer userid) {
        RecommendRule recommendRule = recommendRuleMapper.selectByPrimaryKey(ruleid);
        if(recommendRule == null)
            return new ResultVO<>(Constant.REQUEST_FAIL,"该推荐规则不存在，无法使用！");
        else{
            User user = userMapper.selectByPrimaryKey(userid);
            if(user == null)
                return new ResultVO<>(Constant.REQUEST_FAIL,"获取用户特征失败，请前往个人信息页面更新用户特征！");
            else{
                Date curr = new Date();
                List<Task> allValidTask = taskMapper.selectValidTasks(new Timestamp(curr.getTime()));

                //获取三种策略的单例
                LatestDDLFirstStrategy latestDDLFirstStrategy=LatestDDLFirstStrategy.getInstance();
                TaskAcceptedStrategy taskAcceptedStrategy=TaskAcceptedStrategy.getInstance();
                WorkerStaticMatchingTaskStrategy workerStaticStrategy= WorkerStaticMatchingTaskStrategy.getInstance();

                //对三种策略单例进行初始化，设置向量值等策略特有字段
                List<Task> accepted=new ArrayList<>();
                List<Work> acceptedWork=workMapper.selectByWorker(user.getId());
                for(int k=0;k<acceptedWork.size();k++){
                    accepted.add(taskMapper.selectByPrimaryKey(acceptedWork.get(k).getTaskId()));
                }
                taskAcceptedStrategy.setTaskAccepted(accepted);
                workerStaticStrategy.setVector(RecommendUtil.initUserVector(recommendRule,user));

                List<TaskRecommendVO> latestDDLFirstMatchities=latestDDLFirstStrategy.recommendExecute(allValidTask,userMapper);
                List<TaskRecommendVO> taskAcceptedMatchities=taskAcceptedStrategy.recommendExecute(allValidTask,userMapper);
                List<TaskRecommendVO> workerStaticMatchities=workerStaticStrategy.recommendExecute(allValidTask,userMapper);
                List<TaskRecommendVO> resultMatchities=new ArrayList<>();
                for(int i=0;i<allValidTask.size();i++){
                    TaskRecommendVO temp=new TaskRecommendVO(latestDDLFirstMatchities.get(i));
                    temp.setMatchity( (latestDDLFirstMatchities.get(i).getMatchity()*recommendRule.getTaskLatestDdlFactor()
                                                        +taskAcceptedMatchities.get(i).getMatchity()*recommendRule.getTaskAcceptedFactor()
                                                        +workerStaticMatchities.get(i).getMatchity()*(recommendRule.getTaskPreferFactor()
                                                            +recommendRule.getSkillFactor()
                                                            +recommendRule.getTestEnvFactor())
                            ));
                    resultMatchities.add(temp);
                }
                Collections.sort(resultMatchities,
                        new Comparator<TaskRecommendVO>() {
                            @Override
                            public int compare(TaskRecommendVO o1, TaskRecommendVO o2) {
                                if(o2.getMatchity()-o1.getMatchity()>0)
                                    return 1;
                                else
                                    return -1;
                            }
                        });
                return new ResultVO<>(Constant.REQUEST_SUCCESS,"推荐成功！推荐任务按照匹配度从大到小排列",resultMatchities);
            }
        }
    }
}
